package com.derbysoft.dswitch.adapter.ihg.webservice.protocal_test;

import com.derbysoft.dswitch.adapter.ihg.dto.Request;
import com.derbysoft.dswitch.adapter.ihg.dto.Response;
import com.google.common.base.Preconditions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.*;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HttpContext;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;

import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;

/**
 * User: jason
 * Date: 12-4-20
 * Time: 下午4:24
 */
public abstract class BaseTest<RQ extends Request, RS extends Response> {
    private static final Log LOG = LogFactory.getLog(BaseTest.class);
    private static DefaultHttpClient client;
    protected static final Jaxb2Marshaller MARSHALLER = new Jaxb2Marshaller();

    private static final String ENCODING = "UTF-8";
    private static final String CONTEXT_PATH = "com.derbysoft.dswitch.adapter.ihg.dto";
    private static final String USER_NAME = "9129";
    private static final String PASSWORD = "M@k3mytr1p";

    static {
        client = new DefaultHttpClient();
        client.getParams().setParameter(CookiePolicy.IGNORE_COOKIES, true);
        Credentials credentials = new UsernamePasswordCredentials(USER_NAME, PASSWORD);
        client.getCredentialsProvider().setCredentials(AuthScope.ANY, credentials);
        client.addRequestInterceptor(createInterceptor(), 0);
        client.addResponseInterceptor(createResponseInterceptor(),0);
        MARSHALLER.setContextPath(CONTEXT_PATH);
        try {
            MARSHALLER.afterPropertiesSet();
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }

    private static HttpResponseInterceptor createResponseInterceptor() {
        return new HttpResponseInterceptor() {
            @Override
            public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
                context.setAttribute(ClientContext.COOKIE_SPEC,null);
            }
        };
    }

    protected InputStream sampleXml(String xml) {
        String location = this.getClass().getPackage().getName().replace(".", "//")
                + File.separatorChar + "xml" + File.separatorChar + xml;
        return Preconditions.checkNotNull(
                Thread.currentThread().getContextClassLoader().getResourceAsStream(location),
                "Resource [" + location + "] not found."
        );
    }

    @SuppressWarnings("unchecked")
    protected RS send(String url, RQ request) {
        RS result = null;
        try {
            HttpPost httpPost = new HttpPost(url);

            setRequestBody(MARSHALLER, httpPost, request);

            HttpResponse httpResponse = client.execute(httpPost);

            return (RS) MARSHALLER.unmarshal(new StreamSource(new InputStreamReader(httpResponse.getEntity().getContent(), ENCODING)));
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
        return result;
    }

    private static HttpRequestInterceptor createInterceptor() {
        return new HttpRequestInterceptor() {
            public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
                AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);

                if (authState.getAuthScheme() == null) {
                    CredentialsProvider credentialsProvider = (CredentialsProvider) context.getAttribute(
                            ClientContext.CREDS_PROVIDER);
                    Credentials credentials = credentialsProvider.getCredentials(AuthScope.ANY);
                    if (credentials != null) {
                        authState.update(new BasicScheme(), credentials);
                    }
                }
            }
        };
    }

    private <RQ> void setRequestBody(Jaxb2Marshaller jaxb2Marshaller, HttpPost httpPost, RQ rq) throws Exception {
        httpPost.setHeader("Content-type", "text/xml; charset=UTF-8");
        Writer writer = new StringWriter();
        jaxb2Marshaller.marshal(rq, new StreamResult(writer));
        httpPost.setEntity(new StringEntity(writer.toString(), ContentType.create("text/xml", Consts.UTF_8)));
    }
}
